package com.yang.library.service.bookthread;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.yang.library.bookenum.TCPEnum;
import com.yang.library.entry.Book;
import com.yang.library.entry.User;
import com.yang.library.service.service.BookService;
import com.yang.library.service.service.UserService;
import com.yang.library.service.service.impl.BookServiceImpl;
import com.yang.library.service.service.impl.UserServiceImpl;
import com.yang.library.util.AppContext;
import com.yang.library.util.Constant;

import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

import static com.yang.library.bookenum.State.FAILURE;
import static com.yang.library.bookenum.State.SUCCESS;

public class ServiceThread extends Thread {
    private final Socket socket;
    private final ObjectMapper mapper = AppContext.getInstance().getMapper();
    private final UserService userService = new UserServiceImpl();
    private final BookService bookService = new BookServiceImpl();

    public ServiceThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8)); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8))) {
            while (true) {
                // 这里约定，客户端每次发送一次消息，都要加上换行符\n
                // 然后再服务端按行接收
                String typeLine = reader.readLine();
                if (typeLine == null) {
                    return;
                }
                TCPEnum type = mapper.readValue(typeLine, TCPEnum.class);
                switch (type) {
                    case USER_REGISTER:
                        register(reader, writer);
                        break;
                    case USER_LOGIN:
                        login(reader, writer);
                        break;
                    case USER_DELETE_USER:
                        deleteUser(reader, writer);
                        break;
                    case USER_UPDATE_USER:
                        updateUser(reader, writer);
                        break;
                    case USER_GET_ALL_USERS:
                        getAllUser(writer);
                        break;
                    case USER_GET_USER_BY_NAME:
                        getUserByName(reader, writer);
                        break;
                    case USER_CHANGE_PASSWORD:
                        changePassword(reader, writer);
                        break;
                    case ADD_BOOK:
                        addBook(reader, writer);
                        break;
                    case REMOVE_BOOK:
                        removeBook(reader, writer);
                        break;
                    case UPDATE_BOOK:
                        updateBook(reader, writer);
                        break;
                    case BORROW_BOOK:
                        borrowBook(reader, writer);
                        break;
                    case RETURN_BOOK:
                        returnBook(reader, writer);
                        break;
                    case QUERY_BOOK_BY_TITLE_OR_AUTHOR:
                        getBookByTitleOrAuthor(reader, writer);
                        break;
                    case QUERY_ALL_BOOK:
                        getAllBooks(writer);
                        break;
                    case QUERY_ALL_BORROWED_BOOK:
                        getAllBorrowedBooks(writer);
                        break;
                    case QUERY_MY_BORROWED_BOOK:
                        getBorrowedBooksByName(reader, writer);
                        break;
                    default:
                        return;
                }
            }
        } catch (Exception e) {
            System.out.println("用户服务线程异常");
            throw new RuntimeException(e);
        }
    }

    private void changePassword(BufferedReader reader, BufferedWriter writer) throws Exception {
        String oldMsg = reader.readLine();
        String newMsg = reader.readLine();
        String readMsg = reader.readLine();
        if (oldMsg == null || newMsg == null || readMsg == null) return;
        String oldPwd = mapper.readValue(oldMsg, String.class);
        String newPwd = mapper.readValue(newMsg, String.class);
        String username = mapper.readValue(readMsg, String.class);
        if (userService.changePassword(username, oldPwd, newPwd)) {
            writer.write(mapper.writeValueAsString(SUCCESS) + Constant.NEW_LINE);
            writer.flush();
            return;
        }
        writer.write(mapper.writeValueAsString(FAILURE) + Constant.NEW_LINE);
        writer.flush();
    }

    private void getBorrowedBooksByName(BufferedReader reader, BufferedWriter writer) throws Exception {
        String readMsg = reader.readLine();
        if (readMsg == null) return;
        String username = mapper.readValue(readMsg, String.class);
        List<Book> books = bookService.getAllBorrowedBooks().stream()
                .filter(s -> username.equals(s.getBorrower())).toList();
        writer.write(mapper.writeValueAsString(books) + Constant.NEW_LINE);
        writer.flush();
    }

    private void returnBook(BufferedReader reader, BufferedWriter writer) throws Exception {
        String titleMsg = reader.readLine();
        String userNameMsg = reader.readLine();
        if (titleMsg == null || userNameMsg == null) return;
        String title = mapper.readValue(titleMsg, String.class);
        String userName = mapper.readValue(userNameMsg, String.class);
        if (bookService.returnBook(title, userName)) {
            writer.write(mapper.writeValueAsString(SUCCESS) + Constant.NEW_LINE);
            writer.flush();
            return;
        }
        writer.write(mapper.writeValueAsString(FAILURE) + Constant.NEW_LINE);
        writer.flush();
    }

    private void borrowBook(BufferedReader reader, BufferedWriter writer) throws Exception {
        String titleMsg = reader.readLine();
        String userNameMsg = reader.readLine();
        if (titleMsg == null || userNameMsg == null) return;
        String title = mapper.readValue(titleMsg, String.class);
        String userName = mapper.readValue(userNameMsg, String.class);
        if (title == null || userName == null) return;
        if (bookService.borrowBook(title, userName)) {
            writer.write(mapper.writeValueAsString(SUCCESS) + Constant.NEW_LINE);
            writer.flush();
            return;
        }
        writer.write(mapper.writeValueAsString(FAILURE) + Constant.NEW_LINE);
        writer.flush();
    }

    private void getUserByName(BufferedReader reader, BufferedWriter writer) throws Exception {
        String userMsg = reader.readLine();
        if (userMsg == null) return;
        String username = mapper.readValue(userMsg, String.class);
        User user = userService.getUserByName(username);
        writer.write(mapper.writeValueAsString(user) + Constant.NEW_LINE);
        writer.flush();
    }

    private void getAllUser(BufferedWriter writer) throws Exception {
        List<User> users = userService.getAllUsers();
        writer.write(mapper.writeValueAsString(users) + Constant.NEW_LINE);
        writer.flush();
        System.out.println("查询用户信息成功！");
    }

    private void updateUser(BufferedReader reader, BufferedWriter writer) throws Exception {
        String userMsg = reader.readLine();
        if (userMsg == null) return;
        User user = mapper.readValue(userMsg, User.class);
        if (!userService.updateUser(user.getName(), user)) {
            writer.write(mapper.writeValueAsString(FAILURE) + Constant.NEW_LINE);
            writer.flush();
            return;
        }
        writer.write(mapper.writeValueAsString(SUCCESS) + Constant.NEW_LINE);
        writer.flush();
    }

    private void deleteUser(BufferedReader reader, BufferedWriter writer) throws Exception {
        String readMsg = reader.readLine();
        if (readMsg == null) return;
        String userName = mapper.readValue(readMsg, String.class);
        if (!userService.deleteUser(userName)) {
            writer.write(mapper.writeValueAsString(FAILURE) + Constant.NEW_LINE);
            writer.flush();
            return;
        }
        writer.write(mapper.writeValueAsString(SUCCESS) + Constant.NEW_LINE);
        writer.flush();
    }

    private void login(BufferedReader reader, BufferedWriter writer) throws Exception {
        String nameMsg = reader.readLine();
        String pwdMsg = reader.readLine();
        if (nameMsg == null || pwdMsg == null) return;
        String userName = mapper.readValue(nameMsg, String.class);
        String pwd = mapper.readValue(pwdMsg, String.class);
        Map<com.yang.library.bookenum.State, User> login = userService.login(userName, pwd);
        if (login == null) {
            writer.write(mapper.writeValueAsString(FAILURE) + Constant.NEW_LINE);
            writer.write(mapper.writeValueAsString(Constant.NEW_LINE) + Constant.NEW_LINE);
            writer.flush();
            return;
        }
        writer.write(mapper.writeValueAsString(SUCCESS) + Constant.NEW_LINE);
        writer.write(mapper.writeValueAsString(login.get(SUCCESS).getRole()) + Constant.NEW_LINE);
        writer.flush();
    }

    private void register(BufferedReader reader, BufferedWriter writer) throws Exception {
        String readMsg = reader.readLine();
        if (readMsg == null) return;
        User user = mapper.readValue(readMsg, User.class);
        if (userService.isRegistered(user.getName(), user.getPassword())) {
            writer.write(mapper.writeValueAsString(FAILURE) + Constant.NEW_LINE);
            writer.flush();
            return;
        }
        if (!userService.register(user)) {
            writer.write(mapper.writeValueAsString(FAILURE) + Constant.NEW_LINE);
            writer.flush();
            return;
        }
        writer.write(mapper.writeValueAsString(SUCCESS) + Constant.NEW_LINE);
        writer.flush();
    }

    private void getAllBorrowedBooks(BufferedWriter writer) throws Exception {
        List<Book> books = bookService.getAllBorrowedBooks();
        writer.write(mapper.writeValueAsString(books) + Constant.NEW_LINE);
        writer.flush();
    }

    private void getAllBooks(BufferedWriter writer) throws Exception {
        List<Book> books = bookService.getAllBooks();
        writer.write(mapper.writeValueAsString(books) + Constant.NEW_LINE);
        writer.flush();
    }

    private void getBookByTitleOrAuthor(BufferedReader reader, BufferedWriter writer) throws Exception {
        String requestMsg = reader.readLine();
        if (requestMsg == null) return;
        String titleOrAuthor = mapper.readValue(requestMsg, String.class);
        List<Book> books = bookService.getBookByTitleOrAuthor(titleOrAuthor);
        writer.write(mapper.writeValueAsString(books) + Constant.NEW_LINE);
        writer.flush();
    }

    private void updateBook(BufferedReader reader, BufferedWriter writer) throws Exception {
        String titleMsg = reader.readLine();
        String bookMsg = reader.readLine();
        if (bookMsg == null || titleMsg == null) return;
        String title = mapper.readValue(titleMsg, String.class);
        Book book = mapper.readValue(bookMsg, Book.class);
        if (bookService.updateBook(title, book)) {
            writer.write(mapper.writeValueAsString(com.yang.library.bookenum.State.SUCCESS) + Constant.NEW_LINE);
        } else {
            writer.write(mapper.writeValueAsString(com.yang.library.bookenum.State.FAILURE) + Constant.NEW_LINE);
        }
        writer.flush();
    }

    private void removeBook(BufferedReader reader, BufferedWriter writer) throws Exception {
        String bookMsg = reader.readLine();
        if (bookMsg == null) return;
        String title = mapper.readValue(bookMsg, String.class);
        if (bookService.removeBookByTitle(title)) {
            writer.write(mapper.writeValueAsString(com.yang.library.bookenum.State.SUCCESS) + Constant.NEW_LINE);
        } else {
            writer.write(mapper.writeValueAsString(com.yang.library.bookenum.State.FAILURE) + Constant.NEW_LINE);
        }
        writer.flush();
    }

    private void addBook(BufferedReader reader, BufferedWriter writer) throws Exception {
        String bookMsg = reader.readLine();
        if (bookMsg == null) return;
        Book book = mapper.readValue(bookMsg, Book.class);
        if (bookService.addBook(book)) {
            writer.write(mapper.writeValueAsString(com.yang.library.bookenum.State.SUCCESS) + Constant.NEW_LINE);
        } else {
            writer.write(mapper.writeValueAsString(com.yang.library.bookenum.State.FAILURE) + Constant.NEW_LINE);
        }
        writer.flush();
    }
}
